﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using CommandLine;
using System.IO;
using System.Diagnostics;

namespace DatasetFileConverter
{
	/// <summary>
	/// Esta aplicacion convierte muestras de un formato de entrada a uno diferente.
	/// </summary>
	static class Program
	{
		/// <summary>
		/// Punto de entrada principal para la aplicación.
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{
			if (args.Length > 0)
			{
				try
				{
					var options = new ConsoleOptions();
					var parser = new CommandLineParser(new CommandLineParserSettings(Console.Error));
					if (!parser.ParseArguments(args, options))
						Environment.Exit(1);

					DoCoreTask(options);
				}
				catch (Exception e)
				{
					Console.WriteLine("Error inesperado: {0}", e.Message);
					throw;
				}
			}
			else
			{
				Application.EnableVisualStyles();
				Application.SetCompatibleTextRenderingDefault(false);
				Application.Run(new Form1());
			}
		}

		private static void DoCoreTask(ConsoleOptions options)
		{
			Random rnd = null;
			if (options.Seed.HasValue)
			{
				rnd = new Random(options.Seed.Value);
				Console.WriteLine("Modo aleatorio activado");
			}
			else if (options.Shuffle)
			{
				rnd = new Random();
				Console.WriteLine("Modo aleatorio activado");
			}
			if (options.InputFormat == DatasetFileFormat.Auto)
			{
				options.InputFormat = DetectFormat(options.Input);
			}
			if (options.OutputFormat == DatasetFileFormat.Auto)
			{
				options.OutputFormat = DetectFormat(options.Output);
			}
			if (options.InputFormat == DatasetFileFormat.Destino && options.OutputFormat == DatasetFileFormat.ARFF)
			{
				DestinoToARFF.Convert(options.Input, options.Output, rnd);
			}
			else if (options.InputFormat == DatasetFileFormat.Destino && options.OutputFormat == DatasetFileFormat.CSV)
			{
				DestinoToCSV.Convert(options.Input, options.Output, rnd);
			}
			else
			{
				Console.WriteLine("Conversion entre formatos no soportada: {0} -> {1}", options.InputFormat, options.OutputFormat);
			}
		}

		/// <summary>
		/// Detecta el formato a partir del nombre de archivo
		/// </summary>		
		/// <param name="filename">Nombre de archivo</param>
		private static DatasetFileFormat DetectFormat(string filename)
		{
			DatasetFileFormat fmt;
			var ext = Path.GetExtension(filename);
			switch (ext)
			{
				case "csv": fmt = DatasetFileFormat.CSV; break;
				case "destino": fmt = DatasetFileFormat.Destino; break;
				case "arff": fmt = DatasetFileFormat.ARFF; break;
				default:
					throw new InvalidOperationException("No es posible diferenciar el formato a partir de la extension");
			}
			return fmt;
		}
	}

	public enum DatasetFileFormat
	{
		Auto, CSV, Destino, ARFF
	}

	public class ConsoleOptions
	{
		[Option("negativeIndex", "input", Required = true)]
		public string Input { get; set; }

		[Option("o", "output", Required = true)]
		public string Output { get; set; }

		[Option("if", "inputFormat", HelpText = "Formato de entrada para interpretar el archivo")]
		public DatasetFileFormat InputFormat { get; set; }

		[Option("of", "outputFormat", HelpText = "Formato del archivo de salida")]
		public DatasetFileFormat OutputFormat { get; set; }

		[Option("v", "verbose", HelpText = "Muestra progreso en forma detallada")]
		public bool Verbose { get; set; }

		[Option("s", "shuffle", HelpText = "Aleatoriza la distribucion de muestras")]
		public bool Shuffle { get; set; }

		[Option("seed", "seed", HelpText = "Semilla de generacion de numeros aleatorios para la opcion shuffle")]
		public int? Seed { get; set; }
	}
}
